package cn.qin.xhangapi.controller.auth;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.qin.xhangapi.pojo.LoginLog;
import cn.qin.xhangapi.pojo.SysMenu;
import cn.qin.xhangapi.pojo.SysRole;
import cn.qin.xhangapi.pojo.SysUsers;
import cn.qin.xhangapi.service.LoginLogService;
import cn.qin.xhangapi.service.SysMenuService;
import cn.qin.xhangapi.service.SysRoleService;
import cn.qin.xhangapi.service.SysUsersService;
import cn.qin.xhangapi.util.ClientipUtil;
import cn.qin.xhangapi.util.auth.SysMenuUtil;
import cn.qin.xhangapi.util.md5.MD5Util;
import cn.qin.xhangapi.util.redis.RedisUtil;
import cn.qin.xhangapi.util.response.ResponseResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 权限认证控制器
 *
 * @author 多仔ヾ
 */
@RequestMapping("/api/auth")
@RestController
@CrossOrigin
public class AuthController {

    @Resource
    LoginLogService loginLogService;
    @Resource
    SysUsersService sysUsersService;
    @Resource
    SysRoleService sysRoleService;
    @Resource
    SysMenuService sysMenuService;
    @Resource
    RedisUtil redisUtil;


    /**
     * 系统用户登录
     *
     * @param account  账户账号
     * @param password 账户密码
     * @return cn.duozai.ct.utils.response.ResponseResult
     * @author 多仔ヾ
     */
    @PostMapping("/login")
    public ResponseResult login(@RequestParam(name = "account") String account,
                                @RequestParam(name = "password") String password,
                                @RequestParam(name = "code") String code) {
        // 根据账户账号查询系统用户信息
        SysUsers sysUser = sysUsersService.getOne(new QueryWrapper<SysUsers>().eq("account", account));
        // 判断账户账号是否存在
        if (sysUser == null) {
            return ResponseResult.failure("该账户账号不存在！");
        }
        // 判断密码是否正确
        String md5SaltsPassword = MD5Util.encode(password, sysUser.getSalts());
        if (!md5SaltsPassword.equals(sysUser.getPassword())) {
            return ResponseResult.failure("账户密码错误！");
        }
        //判断验证码
        if (!code.equals(redisUtil.get("code"))) {
            return ResponseResult.failure("验证码错误！");
        }
        // 判断账户状态是否启用
        if (sysUser.getStatus() != 1) {
            return ResponseResult.failure("该账户已被禁用！");
        }
        // 登录成功，调用StpUtil进行登录
        StpUtil.login(sysUser.getId());
        recordLoginLog(sysUser.getId());
        // 由于上面的SysUser没有多表联查，所以要另外查询角色组信息
        SysRole sysRole = sysRoleService.getById(sysUser.getRoleId());
        List<SysMenu> sysMenuList = new ArrayList<>();
        if (sysRole.getIsSuper() == 1) {
            // 最高系统用户角色组拥有所有权限
            sysMenuList = sysMenuService.list();
        } else {
            // 获取该角色组的权限内容，格式为1,2,3,4,5，并格式化成String数组
            String[] perms = sysRole.getPerms().split(",");
            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
            // 公共权限菜单
            queryWrapper.eq("is_public", 1);
            // 或者
            queryWrapper.or();
            // 权限菜单id在该角色组的权限内容当中，表示权限菜单id在perms数组中
            queryWrapper.in("id", perms);
            sysMenuList = sysMenuService.list(queryWrapper);
        }
        // 权限菜单标识列表
        // 遍历提取里面的perms，放到permsArray当中
        List<String> permsArray = new ArrayList<>();
        for (SysMenu sysMenu : sysMenuList) {
            permsArray.add(sysMenu.getPerms());
        }

        // 放到当前用户的session会话当中
        // sysMenuList注意转成树形数据
        StpUtil.getSession().set("sysMenuTreeList", SysMenuUtil.buildTreeMenu(sysMenuList));
        StpUtil.getSession().set("permsArray", permsArray);
        System.out.println(StpUtil.getSession().get("sysMenuTreeList"));

        Map<String, Object> result = new HashMap<>();
        result.put("token", StpUtil.getTokenInfo().getTokenValue());
        // 返回成功结果 + token令牌
        return ResponseResult.success("登录成功", result);
    }

    /**
     * 系统用户注销
     *
     * @return cn.duozai.ct.utils.response.ResponseResult
     * @author 多仔ヾ
     */
    @GetMapping("/logout")
    public ResponseResult logout() {
        StpUtil.logout();
        return ResponseResult.success("注销成功");
    }

    /**
     * 获取当前登录用户信息
     *
     * @return cn.duozai.ct.utils.response.ResponseResult
     * @author 小沁
     */
    @GetMapping("/currentSysUserInfo")
    public ResponseResult<SysUsers> currentSysUserInfo() {
        Long currentSysUserId = StpUtil.getLoginIdAsLong();
        SysUsers sysUsersList = sysUsersService.getByIdWithRelation(currentSysUserId);
        sysUsersList.setPassword(null);
        return ResponseResult.success(sysUsersList);
    }

    //记录登录日志
    public void recordLoginLog(Long id) {
        // 记录登录日志
        String clientip = ClientipUtil.getClientip();
        String realAddress = ClientipUtil.getRealAddres(clientip);

        LoginLog loginLog = new LoginLog();
        loginLog.setUserId(id);
        loginLog.setLoginIp(clientip);
        loginLog.setLoginArea(realAddress);
        loginLog.setLoginTime(DateUtil.current());

        //保存用户登录日志
        loginLogService.save(loginLog);
    }

    /**
     * 获取当前登录系统用户权限菜单树形列表数据
     *
     * @author 多仔ヾ
     * @return cn.duozai.ct.utils.response.ResponseResult
     */
    @GetMapping("/currentSysMenuTreeList")
    public ResponseResult currentSysMenuTreeList() {
        Object sysMenuList = StpUtil.getSession().get("sysMenuTreeList");
        return ResponseResult.success(sysMenuList);
    }

    /**
     * 获取当前登录系统用户权限菜单标识数据
     *
     * @author 多仔ヾ
     * @return cn.duozai.ct.utils.response.ResponseResult
     */
    @GetMapping("/currentSysMenuPerms")
    public ResponseResult currentSysMenuPerms() {
        Object permsArray = StpUtil.getSession().get("permsArray");
        return ResponseResult.success(permsArray);
    }
}
